package com.mugui.base.base;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import cn.hutool.core.lang.Filter;
import com.mugui.base.client.net.classutil.DataSave;

import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import lombok.Getter;

public class ApplicationContext {

    {
        DataSave.context = this;
    }

    @Getter
    private ConcurrentHashMap<String, Object> hashMap = new ConcurrentHashMap<>();

    /**
     * 通过包名扫描包
     *
     * @param packages
     */
    public void init(String... packages) {
        // 扫描包
        try {
            for (String path : packages) {
                Set<Class<?>> scanPackage = ClassUtil.scanPackage(path);
                Iterator<Class<?>> entries = scanPackage.iterator();
                while (entries.hasNext()) {
                    try {
                        Class<?> entryClass = entries.next();
                        if (entryClass != null && Modifier.isPublic(entryClass.getModifiers()) && !Modifier.isInterface(entryClass.getModifiers()) && !Modifier.isAbstract(entryClass.getModifiers()) && !Modifier.isNative(entryClass.getModifiers())) {
                            boolean annotationPresent = entryClass.isAnnotationPresent(Component.class);
                            if (annotationPresent) {
                                System.out.println(
                                        "加载： name=" + entryClass.getSimpleName() + "   class=" + entryClass.getName());
                                Object o = entryClass.newInstance();
                                hashMap.put(entryClass.getName(), o);
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        System.exit(-1);
                    }
                }
            }

            Iterator<Map.Entry<String, Object>> iterator = hashMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, Object> next = iterator.next();
                Object value = next.getValue();
                initBean(value);
            }
            iterator=hashMap.entrySet().iterator();
            while (iterator.hasNext()) {

                Map.Entry<String, Object> next = iterator.next();
                Object value = next.getValue();
                initMethod(value);
            }

            System.out.println("木鬼： 初始化完毕");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void initMethod(Object value) {
        ReflectUtil.getPublicMethods(value.getClass(), method -> {
            if (method.isAnnotationPresent(InitMethod.class)) {
                System.out.println("初始化方法：" + value);
                try {
                    method.invoke(value);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return false;
        });
    }

    public <T> T initBean(T value) {
        System.out.println("初始化：" + value);
        for (Field field : ReflectUtil.getFieldsDirectly(value.getClass(), true)) {
            if (field.isAnnotationPresent(Autowired.class)) {
                field.setAccessible(true);
                System.out.println(
                        "name=" + field.getName() + " 对象名" + hashMap.get(field.getType().getName()));
                try {
                    field.set(value, hashMap.get(field.getType().getName()));
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return value;
    }


    /**
     * 通过class得到唯一对象
     *
     * @param class_name
     * @param <T>
     * @return
     */
    public <T> T getBean(Class<T> class_name) {
        return getBean(class_name.getName());
    }

    public <T> T getBean(String class_name) {
        return (T) hashMap.get(class_name);
    }

    public void putBean(Object o) {
        Object bean = getBean(o.getClass());
        if (bean == null) {
            hashMap.put(o.getClass().getName(), o);
        }
        initBean(o);
        initMethod(o);

    }

    /**
     * 得到加载的所有的class名字
     *
     * @return
     */
    public String[] getBeanDefinitionNames() {
        return hashMap.keySet().toArray(new String[0]);
    }

    /**
     * 通过名字得到class
     *
     * @param type
     * @return
     */
    public Class<?> getType(String type) {
        return hashMap.get(type).getClass();
    }

}
